import pickle
import numpy as np
import freq.DTW
from tqdm import tqdm


def min_dis(samp_list):
    l = len(samp_list)

    dissum = np.zeros((l), float)

    for s, samp in tqdm(enumerate(samp_list)):
        for i, iamp in enumerate(samp_list):
            if (i == s):
                continue
            else:
                dissum[s] += freq.DTW.dtw_distance(samp, iamp)
    min = dissum.argmin()
    return samp_list[min]


'''def dtw_warp(ts_a, ts_b, d=lambda x, y: abs(x - y), mww=np.inf):

    M, N = len(ts_a), len(ts_b)
    cost = np.zeros((M, N),dtype=float)
    ptr = np.zeros((M, N), dtype=0)

    cost[0, 0] = d(ts_a[0], ts_b[0])
    for i in range(1, M):
        cost[i, 0] = cost[i - 1, 0] + d(ts_a[i], ts_b[0])
        ptr[i,0] = 1
    for j in range(1, N):
        cost[0, j] = cost[0, j - 1] + d(ts_a[0], ts_b[j])
        ptr[0,j] = -1
    # Populate rest of cost matrix within window
    for i in range(1, M):
        for j in range(max(1, i - mww), min(N, i + mww)):
            choice,pointer = min(cost[i - 1, j - 1], cost[i, j - 1], cost[i - 1, j])
            cost[i, j] = choice + d(ts_a[i], ts_b[j])
            ptr[i,j] = pointer
    i=M-1
    j=N-1
    warp_ts=np.zeros((N),float)
    while(i>=0):
        if ptr[i,j]==0:
            warp_ts[j]=ts_a[i]
            i-=1
            j-=1
        elif ptr[i,j]==-1:
            warp_ts[j]=ts_a[i]
            j-=1
        elif ptr[i,j]==1:
            sum=0
            num=0
            while(ptr[i,j]==1):
                sum+=ts_a[i]
                num+=1
                i-=1
            warp_ts[j]=sum/num
    return warp_ts'''


def dtwwarp(samp_list, temp_index):
    temp = samp_list[temp_index]
    warp_list = []
    for samp in samp_list:
        warp_list.append(freq.DTW.dtw_warp(samp, temp))
    warp_array = np.array(warp_list)
    return np.average(warp_array, 0)


def lengthwarp(samp_list, length):
    return


def template_generate(samp_list, method=2):
    if (method == 1):
        return min_dis(samp_list)
    elif (method == 2):
        l = len(samp_list)
        length_list = np.zeros((l), float)
        for s, samp in enumerate(samp_list):
            length_list[s] = len(samp)
        length = np.average(length_list)
        print("length" + str(length))
        dis_list = abs(length_list - length)
        temp_index = np.argmin(dis_list)
        return dtwwarp(samp_list, temp_index)
    elif (method == 3):
        l = len(samp_list)
        length_list = np.zeros((l), float)
        for s, samp in enumerate(samp_list):
            length_list[s] = len(samp_list)
        length = np.average(length_list)
        warpsamp_list = lengthwarp(samp_list, length)
        return min_dis(warpsamp_list)
    else:
        print("ERROR：未实现的生成方法！！")


def predict(mfcc_sq, path="./freq/temp_list2.npy"):
    temp_list = np.load(path, allow_pickle=True)
    sample = mfcc_sq
    dis = np.zeros(10, float)
    for t in range(10):
        temp = temp_list[t]
        dis[t] = freq.DTW.dtw_distance(sample, temp)
    return np.argmin(dis)


if __name__ == '__main__':
    method = 2
    samp_list = 0
    f = open('mfcc_list.pkl', 'rb')
    mfcc_list = pickle.load(f)
    f.close()

    '''print(mfcc_list[5][100][20][8])
    print(mfcc_list[5][100].shape)
    print(mfcc_list[5][102].shape)'''

    # temp_list = [None] * 10
    # for n, num_list in enumerate(mfcc_list):
    #     temp_list[n] = template_generate(num_list, method)
    #     print(temp_list[n].shape)
    # np.save("temp_list2.npy", temp_list)
    # k = 0
    # temp_list = np.load("temp_list2.npy", allow_pickle=True)
    # print(temp_list[9].shape)
    # errorss = []
    # for k in range(6):
    #     errors = []
    #     for c in range(10):
    #         error = 0
    #         for i in range(40):
    #             index = k * 40 + i
    #             sample = mfcc_list[c][index]
    #             dis = np.zeros(10, float)
    #             for t in range(10):
    #                 temp = temp_list[t]
    #                 dis[t] = DTW.dtw_distance(sample, temp)
    #             if (np.argmin(dis) != c):
    #                 error += 1
    #         error /= 40
    #         errors.append(error)
    #     errorss.append(errors)
    # print(errorss)
    # np.save("missrate_2.npy", errorss)
    #
    # missrate_1 = np.load("missrate_1.npy")
    # missrate_1 = np.average(missrate_1, 0)
    # missrate_2 = np.load("missrate_2.npy")
    # missrate_2 = np.average(missrate_2, 0)
    # print(missrate_1)
    # print(missrate_2)
